eliminate queues in csv style handling.
authortsteven4 <tsteven4@gmail.com>
Mon, 15 Oct 2018 17:00:54 +0000 (11:00 -0600)
committertsteven4 <tsteven4@gmail.com>
Mon, 15 Oct 2018 17:00:54 +0000 (11:00 -0600)
also:
fix bug with style option encoding.
pass some parameters by const reference.
eliminate some unused time fiddling.

csv_util.cc
csv_util.h
xcsv.cc

index ba1685ed2b5740faec06f21a88c50f7a35f28db8..d35227e3c77965d2da96793cfe7f6d882595189e 100644 (file)
 
  */
 
-#include <QtCore/QRegExp>
-#include <QtCore/QTextStream>
-#include <QtCore/QDebug>
+#include <QtCore/QChar>            // for QChar
+#include <QtCore/QDateTime>        // for QDateTime, QDate
+#include <QtCore/QString>          // for QString, QCharRef
+#include <QtCore/QTextStream>      // for QTextStream
+#include <QtCore/QtGlobal>         // for foreach
 
 #include "csv_util.h"
 #include "defs.h"
@@ -713,8 +715,6 @@ void xcsv_file_init(void)
   xcsv_file.field_encloser = QString();
   xcsv_file.record_delimiter = QString();
   xcsv_file.badchars = QString();
-  xcsv_file.ifield_ct = 0;
-  xcsv_file.ofield_ct = 0;
   xcsv_file.file = nullptr;
   xcsv_file.stream = nullptr;
   xcsv_file.codec = nullptr;
@@ -725,12 +725,8 @@ void xcsv_file_init(void)
   xcsv_file.prologue.clear();
   xcsv_file.epilogue.clear();
 
-  QUEUE_INIT(&xcsv_file.ifield);
-  /* ofield is alloced to allow pointing back at ifields
-   * where applicable.
-   */
-  xcsv_file.ofield = (queue*) xcalloc(sizeof(queue), 1);
-  QUEUE_INIT(xcsv_file.ofield);
+  xcsv_file.ifields.clear();
+  xcsv_file.ofields.clear();
   /*
    * Provide a sane default for CSV _files_.
    */
@@ -742,25 +738,20 @@ void xcsv_file_init(void)
 
 XcsvFile::XcsvFile() {
   is_internal = false;
-  ifield_ct = ofield_ct = 0;
   extension  = nullptr;
 //   xcsv_file_init();
 }
 
-static void validate_fieldmap(const field_map_t* fmp, bool is_output) {
-  QString qkey = fmp->key;
-  QString qval = fmp->val;
-  QString qprintfc = fmp->printfc;
-
-  if (qkey.isEmpty()) {
+static void validate_fieldmap(const field_map& fmp, bool is_output) {
+  if (fmp.key.isEmpty()) {
     Fatal() << MYNAME << ": xcsv style is missing" <<
             (is_output ? "output" : "input") << "field type.";
   }
-  if (!fmp->val) {
-    Fatal() << MYNAME << ": xcsv style" << qkey << "is missing default.";
+  if (fmp.val.isNull()) {
+    Fatal() << MYNAME << ": xcsv style" << fmp.key.constData() << "is missing default.";
   }
-  if (is_output && !fmp->printfc) {
-    Fatal() << MYNAME << ": xcsv style" << qkey << "output is missing format specifier.";
+  if (is_output && fmp.printfc.isNull()) {
+    Fatal() << MYNAME << ": xcsv style" << fmp.key.constData() << "output is missing format specifier.";
   }
 }
 
@@ -769,19 +760,18 @@ static void validate_fieldmap(const field_map_t* fmp, bool is_output) {
 /* usage: xcsv_ifield_add("DESCRIPTION", "", "%s")                           */
 /*****************************************************************************/
 void
-xcsv_ifield_add(const char* key, const char* val, const char* pfc)
+xcsv_ifield_add(const QString& qkey, const QString& qval, const QString& qpfc)
 {
-  field_map_t* fmp = (field_map_t*) xcalloc(sizeof(*fmp), 1);
-  struct xt_mapping* xm = Perfect_Hash::in_word_set(key, strlen(key));
+  QByteArray key = qkey.toUtf8();
+  QByteArray val = qval.toUtf8();
+  QByteArray pfc = qpfc.toUtf8();
 
-  fmp->key = key;
-  fmp->hashed_key = xm ? xm->xt_token : -1;
-  fmp->val = val;
-  fmp->printfc = pfc;
+  struct xt_mapping* xm = Perfect_Hash::in_word_set(key.constData(), strlen(key.constData()));
+
+  field_map fmp(key, val, pfc, xm ? xm->xt_token : -1);
   validate_fieldmap(fmp, false);
 
-  ENQUEUE_TAIL(&xcsv_file.ifield, &fmp->Q);
-  xcsv_file.ifield_ct++;
+  xcsv_file.ifields.append(fmp);
 }
 
 /*****************************************************************************/
@@ -789,20 +779,18 @@ xcsv_ifield_add(const char* key, const char* val, const char* pfc)
 /* usage: xcsv_ofield_add("LAT_DECIMAL", "", "%08.5lf")                      */
 /*****************************************************************************/
 void
-xcsv_ofield_add(const char* key, const char* val, const char* pfc, int options)
+xcsv_ofield_add(const QString& qkey, const QString& qval, const QString& qpfc, unsigned options)
 {
-  field_map_t* fmp = (field_map_t*) xcalloc(sizeof(*fmp), 1);
-  struct xt_mapping* xm = Perfect_Hash::in_word_set(key, strlen(key));
-
-  fmp->key = key;
-  fmp->hashed_key = xm ? xm->xt_token : -1;
-  fmp->val = val;
-  fmp->printfc = pfc;
-  fmp->options = options;
+  QByteArray key = qkey.toUtf8();
+  QByteArray val = qval.toUtf8();
+  QByteArray pfc = qpfc.toUtf8();
+
+  struct xt_mapping* xm = Perfect_Hash::in_word_set(key.constData(), strlen(key.constData()));
+
+  field_map fmp(key, val, pfc, xm ? xm->xt_token : -1, options);
   validate_fieldmap(fmp, true);
 
-  ENQUEUE_TAIL(xcsv_file.ofield, &fmp->Q);
-  xcsv_file.ofield_ct++;
+  xcsv_file.ofields.append(fmp);
 }
 
 /*****************************************************************************/
@@ -810,7 +798,7 @@ xcsv_ofield_add(const char* key, const char* val, const char* pfc, int options)
 /* usage: xcsv_prologue_add("Four score and seven years ago today,")         */
 /*****************************************************************************/
 void
-xcsv_prologue_add(QString prologue)
+xcsv_prologue_add(const QString& prologue)
 {
   xcsv_file.prologue.append(prologue);
 }
@@ -820,7 +808,7 @@ xcsv_prologue_add(QString prologue)
 /* usage: xcsv_epilogue_add("shall not perish from the earth.")              */
 /*****************************************************************************/
 void
-xcsv_epilogue_add(QString epilogue)
+xcsv_epilogue_add(const QString& epilogue)
 {
   xcsv_file.epilogue.append(epilogue);
 }
@@ -968,20 +956,20 @@ gmsd_init(Waypoint* wpt)
 /* usage: xcsv_parse_val("-123.34", *waypt, *field_map)                      */
 /*****************************************************************************/
 static void
-xcsv_parse_val(const char* s, Waypoint* wpt, const field_map_t* fmp,
+xcsv_parse_val(const char* s, Waypoint* wpt, const field_map& fmp,
                route_head** trk)
 {
   const char* enclosure = "";
   geocache_data* gc_data = nullptr;
 
-  if (!fmp->printfc) {
-    fatal(MYNAME ": xcsv style '%s' is missing format specifier", fmp->key);
+  if (fmp.printfc.isNull()) {
+    fatal(MYNAME ": xcsv style '%s' is missing format specifier", fmp.key.constData());
   }
 
-  if (0 == strcmp(fmp->printfc, "\"%s\"")) {
+  if (0 == strcmp(fmp.printfc.constData(), "\"%s\"")) {
     enclosure = "\"";
   }
-  switch (fmp->hashed_key) {
+  switch (fmp.hashed_key) {
   case XT_IGNORE:
     /* IGNORE -- Categorically ignore this... */
     break;
@@ -1190,21 +1178,21 @@ xcsv_parse_val(const char* s, Waypoint* wpt, const field_map_t* fmp,
     wpt->SetCreationTime(yyyymmdd_to_time(s));
     break;
   case XT_GMT_TIME:
-    wpt->SetCreationTime(sscanftime(s, fmp->printfc, 1));
+    wpt->SetCreationTime(sscanftime(s, fmp.printfc.constData(), 1));
     break;
   case XT_LOCAL_TIME:
     if (ugetenv("GPSBABEL_FREEZE_TIME").isNull()) {
-      wpt->creation_time += sscanftime(s, fmp->printfc, 0);
+      wpt->creation_time += sscanftime(s, fmp.printfc.constData(), 0);
     } else {
       /* Force constant time zone for test */
-      wpt->creation_time += sscanftime(s, fmp->printfc, 1);
+      wpt->creation_time += sscanftime(s, fmp.printfc.constData(), 1);
     }
     break;
     /* Useful when time and date are in separate fields
        GMT / Local offset is handled by the two cases above */
   case XT_HMSG_TIME:
   case XT_HMSL_TIME:
-    wpt->creation_time += addhms(s, fmp->printfc);
+    wpt->creation_time += addhms(s, fmp.printfc.constData());
     break;
   case XT_ISO_TIME:
   case XT_ISO_TIME_MS:
@@ -1373,12 +1361,12 @@ xcsv_parse_val(const char* s, Waypoint* wpt, const field_map_t* fmp,
   }
   break;
   case -1:
-    if (strncmp(fmp->key, "LON_10E", 7) == 0) {
-      wpt->longitude = atof(s) / pow(10.0, atof(fmp->key+7));
-    } else if (strncmp(fmp->key, "LAT_10E", 7) == 0) {
-      wpt->latitude = atof(s) / pow(10.0, atof(fmp->key+7));
+    if (strncmp(fmp.key.constData(), "LON_10E", 7) == 0) {
+      wpt->longitude = atof(s) / pow(10.0, atof(fmp.key.constData()+7));
+    } else if (strncmp(fmp.key.constData(), "LAT_10E", 7) == 0) {
+      wpt->latitude = atof(s) / pow(10.0, atof(fmp.key.constData()+7));
     } else {
-      warning(MYNAME ": Unknown style directive: %s\n", fmp->key);
+      warning(MYNAME ": Unknown style directive: %s\n", fmp.key.constData());
     }
     break;
 
@@ -1447,23 +1435,20 @@ xcsv_data_read(void)
       s = csv_lineparse(s, CSTR(xcsv_file.field_delimiter),
                         CSTR(xcsv_file.field_encloser), linecount);
 
-      if (QUEUE_EMPTY(&xcsv_file.ifield)) {
+      if (xcsv_file.ifields.isEmpty()) {
         fatal(MYNAME ": attempt to read, but style '%s' has no IFIELDs in it.\n", CSTR(xcsv_file.description)? CSTR(xcsv_file.description) : "unknown");
       }
 
-      /* reset the ifield queue */
-      queue* elem = QUEUE_FIRST(&xcsv_file.ifield);
+      int ifield_idx = 0;
 
       /* now rip the line apart, advancing the queue for each tear
        * off the beginning of buff since there's no index into queue.
        */
       while (s) {
-        field_map_t* fmp = reinterpret_cast<field_map_t *>(elem);
+        const field_map& fmp = xcsv_file.ifields.at(ifield_idx++);
         xcsv_parse_val(s, wpt_tmp, fmp, &trk);
 
-        elem = QUEUE_NEXT(elem);
-
-        if (elem == &xcsv_file.ifield) {
+        if (ifield_idx >= xcsv_file.ifields.size()) {
           /* we've wrapped the queue. so stop parsing! */
           while (s) {
             s = csv_lineparse(nullptr, "\xff","",linecount);
@@ -1551,7 +1536,6 @@ static void
 xcsv_waypt_pr(const Waypoint* wpt)
 {
   QString buff;
-  queue* elem, *tmp;
   double latitude, longitude;
   int32 utmz;
   double utme, utmn;
@@ -1609,7 +1593,7 @@ xcsv_waypt_pr(const Waypoint* wpt)
   }
 
   int i = 0;
-  QUEUE_FOR_EACH(xcsv_file.ofield, elem, tmp) {
+  for (const auto& fmp : xcsv_file.ofields) {
     double lat = latitude;
     double lon = longitude;
     /*
@@ -1620,39 +1604,37 @@ xcsv_waypt_pr(const Waypoint* wpt)
      */
     int field_is_unknown = 0;
 
-    field_map_t* fmp = reinterpret_cast<field_map_t *>(elem);
-
-    if ((i != 0) && !(fmp->options & OPTIONS_NODELIM)) {
+    if ((i != 0) && !(fmp.options & OPTIONS_NODELIM)) {
       *xcsv_file.stream << write_delimiter;
     }
 
-    if (fmp->options & OPTIONS_ABSOLUTE) {
+    if (fmp.options & OPTIONS_ABSOLUTE) {
       lat = fabs(lat);
       lon = fabs(lon);
     }
 
     i++;
 
-    switch (fmp->hashed_key) {
+    switch (fmp.hashed_key) {
     case XT_IGNORE:
       /* IGNORE -- Write the char printf conversion */
-      buff = QString().sprintf(fmp->printfc, "");
+      buff = QString().sprintf(fmp.printfc.constData(), "");
       break;
     case XT_INDEX:
-      buff = QString().sprintf(fmp->printfc, waypt_out_count + atoi(fmp->val));
+      buff = QString().sprintf(fmp.printfc.constData(), waypt_out_count + atoi(fmp.val.constData()));
       break;
     case XT_CONSTANT: {
-      auto cp = xcsv_get_char_from_constant_table(fmp->val);
+      auto cp = xcsv_get_char_from_constant_table(fmp.val.constData());
       if (!cp.isEmpty()) {
-        buff = QString().sprintf(fmp->printfc, CSTR(cp));
+        buff = QString().sprintf(fmp.printfc.constData(), CSTR(cp));
       } else {
-        buff = QString().sprintf(fmp->printfc, fmp->val);
+        buff = QString().sprintf(fmp.printfc.constData(), fmp.val.constData());
       }
     }
     break;
     case XT_SHORTNAME:
-               buff = QString().sprintf(fmp->printfc,
-                shortname.isEmpty() ? fmp->val : CSTR(shortname));
+               buff = QString().sprintf(fmp.printfc.constData(),
+                shortname.isEmpty() ? fmp.val.constData() : CSTR(shortname));
 
       break;
     case XT_ANYNAME:
@@ -1668,19 +1650,19 @@ xcsv_waypt_pr(const Waypoint* wpt)
         anyname = wpt->notes;
       }
       if (anyname.isEmpty()) {
-        anyname = fmp->val;
+        anyname = fmp.val.constData();
       }
-      buff = QString().sprintf(fmp->printfc, CSTR(anyname));
+      buff = QString().sprintf(fmp.printfc.constData(), CSTR(anyname));
       }
 
       break;
     case XT_DESCRIPTION:
-      buff = QString().sprintf(fmp->printfc,
-                description.isEmpty() ? fmp->val : CSTR(description));
+      buff = QString().sprintf(fmp.printfc.constData(),
+                description.isEmpty() ? fmp.val.constData() : CSTR(description));
       break;
     case XT_NOTES:
-      buff = QString().sprintf(fmp->printfc,
-                wpt->notes.isEmpty() ? fmp->val : CSTR(wpt->notes));
+      buff = QString().sprintf(fmp.printfc.constData(),
+                wpt->notes.isEmpty() ? fmp.val.constData() : CSTR(wpt->notes));
       break;
     case XT_URL: {
       if (xcsv_urlbase) {
@@ -1688,106 +1670,106 @@ xcsv_waypt_pr(const Waypoint* wpt)
       }
       if (wpt->HasUrlLink()) {
         UrlLink l = wpt->GetUrlLink();
-        buff += QString().sprintf(fmp->printfc, CSTR(l.url_));
+        buff += QString().sprintf(fmp.printfc.constData(), CSTR(l.url_));
       } else {
-        buff += QString().sprintf(fmp->printfc, fmp->val && *fmp->val ? fmp->val : "\"\"");
+        buff += QString().sprintf(fmp.printfc.constData(), fmp.val.constData() && *fmp.val.constData() ? fmp.val.constData() : "\"\"");
       }
     }
     break;
     case XT_URL_LINK_TEXT:
       if (wpt->HasUrlLink()) {
         UrlLink l = wpt->GetUrlLink();
-        buff = QString().sprintf(fmp->printfc,
-                 !l.url_link_text_.isEmpty() ? CSTR(l.url_link_text_) : fmp->val);
+        buff = QString().sprintf(fmp.printfc.constData(),
+                 !l.url_link_text_.isEmpty() ? CSTR(l.url_link_text_) : fmp.val.constData());
       }
       break;
     case XT_ICON_DESCR:
-      buff = QString().sprintf(fmp->printfc,
+      buff = QString().sprintf(fmp.printfc.constData(),
                 (!wpt->icon_descr.isNull()) ?
-                CSTR(wpt->icon_descr) : fmp->val);
+                CSTR(wpt->icon_descr) : fmp.val.constData());
       break;
 
       /* LATITUDE CONVERSION***********************************************/
     case XT_LAT_DECIMAL:
       /* latitude as a pure decimal value */
-      buff = QString().sprintf(fmp->printfc, lat);
+      buff = QString().sprintf(fmp.printfc.constData(), lat);
       break;
     case XT_LAT_DECIMALDIR:
       /* latitude as a decimal value with N/S after it */
-      buff = QString().sprintf(fmp->printfc, fabs(lat),
+      buff = QString().sprintf(fmp.printfc.constData(), fabs(lat),
                LAT_DIR(lat));
       break;
     case XT_LAT_DIRDECIMAL:
       /* latitude as a decimal value with N/S before it */
-      buff = QString().sprintf(fmp->printfc,
+      buff = QString().sprintf(fmp.printfc.constData(),
                LAT_DIR(lat),
                fabs(lat));
       break;
     case XT_LAT_INT32DEG:
       /* latitude as an integer offset from 0 degrees */
-      buff = QString().sprintf(fmp->printfc,
+      buff = QString().sprintf(fmp.printfc.constData(),
                 dec_to_intdeg(lat));
       break;
     case XT_LAT_DDMMDIR:
       /*latitude as (degrees * 100) + decimal minutes, with N/S after it */
-      buff = dec_to_human(fmp->printfc, "SN", degrees2ddmm(lat));
+      buff = dec_to_human(fmp.printfc.constData(), "SN", degrees2ddmm(lat));
       break;
     case XT_LAT_HUMAN_READABLE:
-      buff = dec_to_human(fmp->printfc, "SN", lat);
+      buff = dec_to_human(fmp.printfc.constData(), "SN", lat);
       break;
     case XT_LAT_NMEA:
-      buff = QString().sprintf(fmp->printfc, degrees2ddmm(lat));
+      buff = QString().sprintf(fmp.printfc.constData(), degrees2ddmm(lat));
       break;
       // case XT_LAT_10E is handled outside the switch.
       /* LONGITUDE CONVERSIONS*********************************************/
     case XT_LON_DECIMAL:
       /* longitude as a pure decimal value */
-      buff = QString().sprintf(fmp->printfc, lon);
+      buff = QString().sprintf(fmp.printfc.constData(), lon);
       break;
     case XT_LON_DECIMALDIR:
       /* latitude as a decimal value with N/S after it */
-      buff = QString().sprintf(fmp->printfc,
+      buff = QString().sprintf(fmp.printfc.constData(),
                fabs(lon),
                LON_DIR(lon));
       break;
     case XT_LON_DIRDECIMAL:
       /* latitude as a decimal value with N/S before it */
-      buff = QString().sprintf(fmp->printfc,
+      buff = QString().sprintf(fmp.printfc.constData(),
                LON_DIR(lon),
                fabs(lon));
       break;
     case XT_LON_INT32DEG:
       /* longitudee as an integer offset from 0 degrees */
-      buff = QString().sprintf(fmp->printfc,
+      buff = QString().sprintf(fmp.printfc.constData(),
                 dec_to_intdeg(lon));
       break;
     case XT_LON_DDMMDIR:
       /* longidute as (degrees * 100) + decimal minutes, with W/E after it*/
-      buff = dec_to_human(fmp->printfc, "WE", degrees2ddmm(lon));
+      buff = dec_to_human(fmp.printfc.constData(), "WE", degrees2ddmm(lon));
       break;
     case XT_LON_HUMAN_READABLE:
-      buff = dec_to_human(fmp->printfc, "WE", lon);
+      buff = dec_to_human(fmp.printfc.constData(), "WE", lon);
       break;
     case XT_LATLON_HUMAN_READABLE:
-      buff = dec_to_human(fmp->printfc, "SN", lat);
+      buff = dec_to_human(fmp.printfc.constData(), "SN", lat);
         buff += " ";
-      buff += dec_to_human(fmp->printfc, "WE", lon);
+      buff += dec_to_human(fmp.printfc.constData(), "WE", lon);
       // Tidy up leading, trailing, middle whitespace.
       buff = buff.simplified();
       break;
     case XT_LON_NMEA:
-      buff = QString().sprintf(fmp->printfc, degrees2ddmm(lon));
+      buff = QString().sprintf(fmp.printfc.constData(), degrees2ddmm(lon));
       break;
       // case XT_LON_10E is handled outside the switch.
       /* DIRECTIONS *******************************************************/
     case XT_LAT_DIR:
       /* latitude N/S as a char */
-      buff = QString().sprintf(fmp->printfc,
+      buff = QString().sprintf(fmp.printfc.constData(),
                 LAT_DIR(lat));
       break;
     case XT_LON_DIR:
       /* longitude E/W as a char */
-      buff = QString().sprintf(fmp->printfc,
+      buff = QString().sprintf(fmp.printfc.constData(),
                 LON_DIR(lon));
       break;
 
@@ -1798,7 +1780,7 @@ xcsv_waypt_pr(const Waypoint* wpt)
       if (! GPS_Math_WGS84_To_UKOSMap_M(wpt->latitude, wpt->longitude, &east, &north, map))
         fatal(MYNAME ": Position (%.5f/%.5f) outside of BNG.\n",
               wpt->latitude, wpt->longitude);
-      buff = QString().sprintf(fmp->printfc, map, (int)(east + 0.5), (int)(north + 0.5));
+      buff = QString().sprintf(fmp.printfc.constData(), map, (int)(east + 0.5), (int)(north + 0.5));
     }
     break;
     case XT_UTM: {
@@ -1807,18 +1789,18 @@ xcsv_waypt_pr(const Waypoint* wpt)
                                &utme, &utmn, &utmz, &utmzc);
       snprintf(tbuf, sizeof(tbuf), "%d%c %6.0f %7.0f",
                utmz, utmzc, utme, utmn);
-      buff = QString().sprintf(fmp->printfc, tbuf);
+      buff = QString().sprintf(fmp.printfc.constData(), tbuf);
     }
     break;
     case XT_UTM_ZONE:
       GPS_Math_WGS84_To_UTM_EN(wpt->latitude, wpt->longitude,
                                &utme, &utmn, &utmz, &utmzc);
-      buff = QString().sprintf(fmp->printfc, utmz);
+      buff = QString().sprintf(fmp.printfc.constData(), utmz);
       break;
     case XT_UTM_ZONEC:
       GPS_Math_WGS84_To_UTM_EN(wpt->latitude, wpt->longitude,
                                &utme, &utmn, &utmz, &utmzc);
-      buff = QString().sprintf(fmp->printfc, utmzc);
+      buff = QString().sprintf(fmp.printfc.constData(), utmzc);
       break;
     case XT_UTM_ZONEF: {
       char tbuf[10];
@@ -1826,29 +1808,29 @@ xcsv_waypt_pr(const Waypoint* wpt)
                                &utme, &utmn, &utmz, &utmzc);
       tbuf[0] = 0;
       snprintf(tbuf, sizeof(tbuf), "%d%c", utmz, utmzc);
-      buff = QString().sprintf(fmp->printfc, tbuf);
+      buff = QString().sprintf(fmp.printfc.constData(), tbuf);
     }
     break;
     case XT_UTM_NORTHING:
       GPS_Math_WGS84_To_UTM_EN(wpt->latitude, wpt->longitude,
                                &utme, &utmn, &utmz, &utmzc);
-      buff = QString().sprintf(fmp->printfc, utmn);
+      buff = QString().sprintf(fmp.printfc.constData(), utmn);
       break;
     case XT_UTM_EASTING:
       GPS_Math_WGS84_To_UTM_EN(wpt->latitude, wpt->longitude,
                                &utme, &utmn, &utmz, &utmzc);
-      buff = QString().sprintf(fmp->printfc, utme);
+      buff = QString().sprintf(fmp.printfc.constData(), utme);
       break;
 
       /* ALTITUDE CONVERSIONS**********************************************/
     case XT_ALT_FEET:
       /* altitude in feet as a decimal value */
-      buff = QString().sprintf(fmp->printfc,
+      buff = QString().sprintf(fmp.printfc.constData(),
                 METERS_TO_FEET(wpt->altitude));
       break;
     case XT_ALT_METERS:
       /* altitude in meters as a decimal value */
-      buff = QString().sprintf(fmp->printfc,
+      buff = QString().sprintf(fmp.printfc.constData(),
                 wpt->altitude);
       break;
 
@@ -1858,71 +1840,71 @@ xcsv_waypt_pr(const Waypoint* wpt)
     case XT_PATH_DISTANCE_MILES:
       /* path (route/track) distance in miles */
       if (wpt->odometer_distance) {
-        buff = QString().sprintf(fmp->printfc, METERS_TO_MILES(wpt->odometer_distance));
+        buff = QString().sprintf(fmp.printfc.constData(), METERS_TO_MILES(wpt->odometer_distance));
       } else {
-        buff = QString().sprintf(fmp->printfc, pathdist);
+        buff = QString().sprintf(fmp.printfc.constData(), pathdist);
       }
       break;
     case XT_PATH_DISTANCE_METERS:
       /* path (route/track) distance in meters */
       if (wpt->odometer_distance) {
-        buff = QString().sprintf(fmp->printfc, wpt->odometer_distance);
+        buff = QString().sprintf(fmp.printfc.constData(), wpt->odometer_distance);
       } else {
-        buff = QString().sprintf(fmp->printfc, MILES_TO_METERS(pathdist));
+        buff = QString().sprintf(fmp.printfc.constData(), MILES_TO_METERS(pathdist));
       }
       break;
     case XT_PATH_DISTANCE_KM:
       /* path (route/track) distance in kilometers */
       if (wpt->odometer_distance) {
-        buff = QString().sprintf(fmp->printfc, wpt->odometer_distance / 1000.0);
+        buff = QString().sprintf(fmp.printfc.constData(), wpt->odometer_distance / 1000.0);
       } else {
-        buff = QString().sprintf(fmp->printfc, MILES_TO_METERS(pathdist) / 1000.0);
+        buff = QString().sprintf(fmp.printfc.constData(), MILES_TO_METERS(pathdist) / 1000.0);
       }
       break;
     case XT_PATH_SPEED:
-      buff = QString().sprintf(fmp->printfc, wpt->speed);
+      buff = QString().sprintf(fmp.printfc.constData(), wpt->speed);
       break;
     case XT_PATH_SPEED_KPH:
-      buff = QString().sprintf(fmp->printfc, MPS_TO_KPH(wpt->speed));
+      buff = QString().sprintf(fmp.printfc.constData(), MPS_TO_KPH(wpt->speed));
       break;
     case XT_PATH_SPEED_MPH:
-      buff = QString().sprintf(fmp->printfc, MPS_TO_MPH(wpt->speed));
+      buff = QString().sprintf(fmp.printfc.constData(), MPS_TO_MPH(wpt->speed));
       break;
     case XT_PATH_SPEED_KNOTS:
-      buff = QString().sprintf(fmp->printfc, MPS_TO_KNOTS(wpt->speed));
+      buff = QString().sprintf(fmp.printfc.constData(), MPS_TO_KNOTS(wpt->speed));
       break;
     case XT_PATH_COURSE:
-      buff = QString().sprintf(fmp->printfc, wpt->course);
+      buff = QString().sprintf(fmp.printfc.constData(), wpt->course);
       break;
 
       /* HEART RATE CONVERSION***********************************************/
     case XT_HEART_RATE:
-      buff = QString().sprintf(fmp->printfc, wpt->heartrate);
+      buff = QString().sprintf(fmp.printfc.constData(), wpt->heartrate);
       break;
       /* CADENCE CONVERSION***********************************************/
     case XT_CADENCE:
-      buff = QString().sprintf(fmp->printfc, wpt->cadence);
+      buff = QString().sprintf(fmp.printfc.constData(), wpt->cadence);
       break;
       /* POWER CONVERSION***********************************************/
     case XT_POWER:
-      buff = QString().sprintf(fmp->printfc, wpt->power);
+      buff = QString().sprintf(fmp.printfc.constData(), wpt->power);
       break;
     case XT_TEMPERATURE:
-      buff = QString().sprintf(fmp->printfc, wpt->temperature);
+      buff = QString().sprintf(fmp.printfc.constData(), wpt->temperature);
       break;
     case XT_TEMPERATURE_F:
-      buff = QString().sprintf(fmp->printfc, CELSIUS_TO_FAHRENHEIT(wpt->temperature));
+      buff = QString().sprintf(fmp.printfc.constData(), CELSIUS_TO_FAHRENHEIT(wpt->temperature));
       break;
       /* TIME CONVERSIONS**************************************************/
     case XT_EXCEL_TIME:
       /* creation time as an excel (double) time */
-      buff = QString().sprintf(fmp->printfc, TIMET_TO_EXCEL(wpt->GetCreationTime().toTime_t()));
+      buff = QString().sprintf(fmp.printfc.constData(), TIMET_TO_EXCEL(wpt->GetCreationTime().toTime_t()));
       break;
     case XT_TIMET_TIME:
       /* time as a time_t variable */
     {
       time_t tt = wpt->GetCreationTime().toTime_t();
-      buff = QString().sprintf(fmp->printfc, tt);
+      buff = QString().sprintf(fmp.printfc.constData(), tt);
     }
     break;
 
@@ -1934,19 +1916,19 @@ xcsv_waypt_pr(const Waypoint* wpt)
     }
     break;
     case XT_YYYYMMDD_TIME:
-      buff = QString().sprintf(fmp->printfc, time_to_yyyymmdd(wpt->GetCreationTime()));
+      buff = QString().sprintf(fmp.printfc.constData(), time_to_yyyymmdd(wpt->GetCreationTime()));
       break;
     case XT_GMT_TIME:
-      buff = writetime(fmp->printfc, wpt->GetCreationTime(), true);
+      buff = writetime(fmp.printfc.constData(), wpt->GetCreationTime(), true);
       break;
     case XT_LOCAL_TIME:
-      buff = writetime(fmp->printfc, wpt->GetCreationTime(), false);
+      buff = writetime(fmp.printfc.constData(), wpt->GetCreationTime(), false);
       break;
     case XT_HMSG_TIME:
-      buff = writehms(fmp->printfc, wpt->GetCreationTime(), 1);
+      buff = writehms(fmp.printfc.constData(), wpt->GetCreationTime(), 1);
       break;
     case XT_HMSL_TIME:
-      buff = writehms(fmp->printfc, wpt->GetCreationTime(), 0);
+      buff = writehms(fmp.printfc.constData(), wpt->GetCreationTime(), 0);
       break;
     case XT_ISO_TIME:
       buff = writetime("%Y-%m-%dT%H:%M:%SZ", wpt->GetCreationTime(), true);
@@ -1955,93 +1937,93 @@ xcsv_waypt_pr(const Waypoint* wpt)
       buff = wpt->GetCreationTime().toPrettyString();
       break;
     case XT_GEOCACHE_LAST_FOUND:
-      buff = QString().sprintf(fmp->printfc, time_to_yyyymmdd(wpt->gc_data->last_found));
+      buff = QString().sprintf(fmp.printfc.constData(), time_to_yyyymmdd(wpt->gc_data->last_found));
       break;
       /* GEOCACHE STUFF **************************************************/
     case XT_GEOCACHE_DIFF:
       /* Geocache Difficulty as a double */
-      buff = QString().sprintf(fmp->printfc, wpt->gc_data->diff / 10.0);
+      buff = QString().sprintf(fmp.printfc.constData(), wpt->gc_data->diff / 10.0);
       field_is_unknown = !wpt->gc_data->diff;
       break;
     case XT_GEOCACHE_TERR:
       /* Geocache Terrain as a double */
-      buff = QString().sprintf(fmp->printfc, wpt->gc_data->terr / 10.0);
+      buff = QString().sprintf(fmp.printfc.constData(), wpt->gc_data->terr / 10.0);
       field_is_unknown = !wpt->gc_data->terr;
       break;
     case XT_GEOCACHE_CONTAINER:
       /* Geocache Container */
-      buff = QString().sprintf(fmp->printfc, gs_get_container(wpt->gc_data->container));
+      buff = QString().sprintf(fmp.printfc.constData(), gs_get_container(wpt->gc_data->container));
       field_is_unknown = wpt->gc_data->container == gc_unknown;
       break;
     case XT_GEOCACHE_TYPE:
       /* Geocache Type */
-      buff = QString().sprintf(fmp->printfc, gs_get_cachetype(wpt->gc_data->type));
+      buff = QString().sprintf(fmp.printfc.constData(), gs_get_cachetype(wpt->gc_data->type));
       field_is_unknown = wpt->gc_data->type == gt_unknown;
       break;
     case XT_GEOCACHE_HINT:
-      buff = QString().sprintf(fmp->printfc, CSTR(wpt->gc_data->hint));
+      buff = QString().sprintf(fmp.printfc.constData(), CSTR(wpt->gc_data->hint));
       field_is_unknown = !wpt->gc_data->hint.isEmpty();
       break;
     case XT_GEOCACHE_PLACER:
-      buff = QString().sprintf(fmp->printfc, CSTR(wpt->gc_data->placer));
+      buff = QString().sprintf(fmp.printfc.constData(), CSTR(wpt->gc_data->placer));
       field_is_unknown = !wpt->gc_data->placer.isEmpty();
       break;
     case XT_GEOCACHE_ISAVAILABLE:
       if (wpt->gc_data->is_available == status_false) {
-        buff = QString().sprintf(fmp->printfc, "False");
+        buff = QString().sprintf(fmp.printfc.constData(), "False");
       } else if (wpt->gc_data->is_available == status_true) {
-        buff = QString().sprintf(fmp->printfc, "True");
+        buff = QString().sprintf(fmp.printfc.constData(), "True");
       } else {
-        buff = QString().sprintf(fmp->printfc, "Unknown");
+        buff = QString().sprintf(fmp.printfc.constData(), "Unknown");
       }
       break;
     case XT_GEOCACHE_ISARCHIVED:
       if (wpt->gc_data->is_archived == status_false) {
-        buff = QString().sprintf(fmp->printfc, "False");
+        buff = QString().sprintf(fmp.printfc.constData(), "False");
       } else if (wpt->gc_data->is_archived == status_true) {
-        buff = QString().sprintf(fmp->printfc, "True");
+        buff = QString().sprintf(fmp.printfc.constData(), "True");
       } else {
-        buff = QString().sprintf(fmp->printfc, "Unknown");
+        buff = QString().sprintf(fmp.printfc.constData(), "Unknown");
       }
       break;
       /* Tracks and Routes ***********************************************/
     case XT_TRACK_NEW:
       if (csv_track) {
         if (WAYPT_HAS(wpt,new_trkseg)) {
-          buff = QString().sprintf(fmp->printfc, 1);
+          buff = QString().sprintf(fmp.printfc.constData(), 1);
         } else {
-          buff = QString().sprintf(fmp->printfc, 0);
+          buff = QString().sprintf(fmp.printfc.constData(), 0);
         }
       }
       break;
     case XT_TRACK_NAME:
       if (csv_track) {
         QString r = csv_track->rte_name;
-        buff = QString().sprintf(fmp->printfc, NONULL(r));
+        buff = QString().sprintf(fmp.printfc.constData(), NONULL(r));
       }
       break;
     case XT_ROUTE_NAME:
       if (csv_route) {
         QString r = csv_route->rte_name;
-        buff = QString().sprintf(fmp->printfc, NONULL(r));
+        buff = QString().sprintf(fmp.printfc.constData(), NONULL(r));
       }
       break;
 
       /* GPS STUFF *******************************************************/
     case XT_GPS_HDOP:
-      buff = QString().sprintf(fmp->printfc, wpt->hdop);
+      buff = QString().sprintf(fmp.printfc.constData(), wpt->hdop);
       field_is_unknown = !wpt->hdop;
       break;
     case XT_GPS_VDOP:
-      buff = QString().sprintf(fmp->printfc, wpt->vdop);
+      buff = QString().sprintf(fmp.printfc.constData(), wpt->vdop);
       field_is_unknown = !wpt->vdop;
       break;
     case XT_GPS_PDOP:
-      buff = QString().sprintf(fmp->printfc, wpt->pdop);
+      buff = QString().sprintf(fmp.printfc.constData(), wpt->pdop);
       field_is_unknown = !wpt->pdop;
       break;
     case XT_GPS_SAT:
-      buff = QString().sprintf(fmp->printfc, wpt->sat);
+      buff = QString().sprintf(fmp.printfc.constData(), wpt->sat);
       field_is_unknown = !wpt->sat;
       break;
     case XT_GPS_FIX: {
@@ -2067,66 +2049,66 @@ xcsv_waypt_pr(const Waypoint* wpt)
         fix = "pps";
         break;
       }
-      buff = QString().sprintf(fmp->printfc, fix);
+      buff = QString().sprintf(fmp.printfc.constData(), fix);
     }
     break;
     /* GMSD ************************************************************/
     case XT_COUNTRY: {
       garmin_fs_t* gmsd = GMSD_FIND(wpt);
-      buff = QString().sprintf(fmp->printfc, GMSD_GET(country, ""));
+      buff = QString().sprintf(fmp.printfc.constData(), GMSD_GET(country, ""));
     }
     break;
     case XT_STATE: {
       garmin_fs_t* gmsd = GMSD_FIND(wpt);
-      buff = QString().sprintf(fmp->printfc, GMSD_GET(state, ""));
+      buff = QString().sprintf(fmp.printfc.constData(), GMSD_GET(state, ""));
     }
     break;
     case XT_CITY: {
       garmin_fs_t* gmsd = GMSD_FIND(wpt);
-      buff = QString().sprintf(fmp->printfc, GMSD_GET(city, ""));
+      buff = QString().sprintf(fmp.printfc.constData(), GMSD_GET(city, ""));
     }
     break;
     case XT_POSTAL_CODE: {
       garmin_fs_t* gmsd = GMSD_FIND(wpt);
-      buff = QString().sprintf(fmp->printfc, GMSD_GET(postal_code, ""));
+      buff = QString().sprintf(fmp.printfc.constData(), GMSD_GET(postal_code, ""));
     }
     break;
     case XT_STREET_ADDR: {
       garmin_fs_t* gmsd = GMSD_FIND(wpt);
-      buff = QString().sprintf(fmp->printfc, GMSD_GET(addr, ""));
+      buff = QString().sprintf(fmp.printfc.constData(), GMSD_GET(addr, ""));
     }
     break;
     case XT_PHONE_NR: {
       garmin_fs_t* gmsd = GMSD_FIND(wpt);
-      buff = QString().sprintf(fmp->printfc, GMSD_GET(phone_nr, ""));
+      buff = QString().sprintf(fmp.printfc.constData(), GMSD_GET(phone_nr, ""));
     }
     break;
     case XT_FACILITY: {
       garmin_fs_t* gmsd = GMSD_FIND(wpt);
-      buff = QString().sprintf(fmp->printfc, GMSD_GET(facility, ""));
+      buff = QString().sprintf(fmp.printfc.constData(), GMSD_GET(facility, ""));
     }
     break;
     /* specials */
     case XT_FILENAME:
-      buff = QString().sprintf(fmp->printfc, wpt->session->filename);
+      buff = QString().sprintf(fmp.printfc.constData(), wpt->session->filename);
       break;
     case XT_FORMAT:
-      buff = QString().sprintf(fmp->printfc, wpt->session->name);
+      buff = QString().sprintf(fmp.printfc.constData(), wpt->session->name);
       break;
     case -1:
-      if (strncmp(fmp->key, "LON_10E", 7) == 0) {
-        buff = QString().sprintf(fmp->printfc, lon * pow(10.0, atof(fmp->key+7)));
-      } else if (strncmp(fmp->key, "LAT_10E", 7) == 0) {
-        buff = QString().sprintf(fmp->printfc, lat * pow(10.0, atof(fmp->key+7)));
+      if (strncmp(fmp.key.constData(), "LON_10E", 7) == 0) {
+        buff = QString().sprintf(fmp.printfc.constData(), lon * pow(10.0, atof(fmp.key.constData()+7)));
+      } else if (strncmp(fmp.key.constData(), "LAT_10E", 7) == 0) {
+        buff = QString().sprintf(fmp.printfc.constData(), lat * pow(10.0, atof(fmp.key.constData()+7)));
       }
       break;
     default:
-      warning(MYNAME ": Unknown style directive: %s\n", fmp->key);
+      warning(MYNAME ": Unknown style directive: %s\n", fmp.key.constData());
       break;
     }
     QString obuff = csv_stringclean(buff, xcsv_file.badchars);
 
-    if (field_is_unknown && fmp->options & OPTIONS_OPTIONAL) {
+    if (field_is_unknown && fmp.options & OPTIONS_OPTIONAL) {
       continue;
     }
 
@@ -2138,7 +2120,7 @@ xcsv_waypt_pr(const Waypoint* wpt)
     /* As a special case (pronounced "horrible hack") we allow
      * ""%s"" to smuggle bad characters through.
      */
-    if (0 == strcmp(fmp->printfc, "\"%s\"")) {
+    if (0 == strcmp(fmp.printfc.constData(), "\"%s\"")) {
       obuff = '"' + obuff + '"';
     }
     *xcsv_file.stream << obuff;
@@ -2170,13 +2152,7 @@ xcsv_replace_tokens(const QString& original) {
     // Don't do potentially expensive replacements if token prefix
     // isn't present;
     if (original.contains("__")) {
-      struct tm tm;
       time_t my_time = gpsbabel_time;
-      if (my_time == 0) {  /* testo script ? */
-        tm = *gmtime(&my_time);
-      } else {
-        tm = *localtime(&my_time);
-      }
 
       replacement.replace("__FILE__", xcsv_file.fname);
       replacement.replace("__VERSION__", my_time == 0 ? "" : gpsbabel_version);
@@ -2203,21 +2179,11 @@ xcsv_replace_tokens(const QString& original) {
 void
 xcsv_data_write(void)
 {
-  time_t time;
-  struct tm tm;
-
   /* reset the index counter */
   waypt_out_count = 0;
 
-  time = gpsbabel_time;
-  if (time == 0) {     /* testo script ? */
-    tm = *gmtime(&time);
-  } else {
-    tm = *localtime(&time);
-  }
-
   /* output prologue lines, if any. */
-  for (auto line : xcsv_file.prologue) {
+  for (const auto& line : xcsv_file.prologue) {
    QString line_to_write = xcsv_replace_tokens(line);
     *xcsv_file.stream << line_to_write <<  xcsv_file.record_delimiter;
   }
@@ -2233,7 +2199,7 @@ xcsv_data_write(void)
   }
 
   /* output epilogue lines, if any. */
-  for (auto line : xcsv_file.epilogue) {
+  for (const auto& line : xcsv_file.epilogue) {
     QString line_to_write = xcsv_replace_tokens(line);
     *xcsv_file.stream << line_to_write << xcsv_file.record_delimiter;
   }
index 64911af35c41260151d844a9f8f49a4e443cb700..25925194f5a7dacf8c9c1a6d5bf21d31e8854306 100644 (file)
@@ -63,39 +63,47 @@ void
 xcsv_file_init(void);
 
 void
-xcsv_prologue_add(QString);
+xcsv_prologue_add(const QString&);
 
 void
-xcsv_epilogue_add(QString);
+xcsv_epilogue_add(const QString&);
 
 void
-xcsv_ifield_add(const char*, const char*, const char*);
+xcsv_ifield_add(const QString&, const QString&, const QString&);
 
 void
-xcsv_ofield_add(const char*, const char*, const char*, int options);
+xcsv_ofield_add(const QString&, const QString&, const QString&, unsigned options);
 
 void
 xcsv_destroy_style(void);
 
 QString
-xcsv_get_char_from_constant_table(QString key);
+xcsv_get_char_from_constant_table(const QString& key);
 
 /****************************************************************************/
 /* types required for various xcsv functions                                */
 /****************************************************************************/
 
 /* something to map fields to waypts */
-#define OPTIONS_NODELIM 1
-#define OPTIONS_ABSOLUTE 2
-#define OPTIONS_OPTIONAL 3
-typedef struct field_map {
-  queue Q;
-  const char* key;
-  const char* val;
-  const char* printfc;
-  int hashed_key;
-  int options;
-} field_map_t;
+#define OPTIONS_NODELIM 1U
+#define OPTIONS_ABSOLUTE 2U
+#define OPTIONS_OPTIONAL 4U
+struct field_map {
+public:
+  // We use QByteArrays because consumers want char* data and QByteArrays supply this through constData().
+  // If we used QStrings, then we would have to convert to QByteArrays to get the char* data.
+  // If we use char* then we have to manage memory allocation/deallocation.
+  // TODO: when consumers use QStrings then we can store QStrings instead of QByteArrays.
+  QByteArray key;
+  QByteArray val;
+  QByteArray printfc;
+  int hashed_key{0};
+  unsigned options{0};
+
+  field_map() = default;
+  field_map(const QByteArray& k, const QByteArray& v, const QByteArray& p, int hk) : key{k},val{v},printfc{p},hashed_key{hk} {}
+  field_map(const QByteArray& k, const QByteArray& v, const QByteArray& p, int hk, unsigned o) : key{k},val{v},printfc{p},hashed_key{hk},options{o} {}
+};
 
 /* something to map config file constants to chars */
 typedef struct char_map {
@@ -125,18 +133,13 @@ class XcsvFile {
   QStringList epilogue;
 
   QString field_delimiter;     /* comma, quote, etc... */
-  QString field_encloser;      /* doublequote, etc... */
+  QString field_encloser;              /* doublequote, etc... */
   QString record_delimiter;    /* newline, c/r, etc... */
 
   QString badchars;            /* characters we never write to output */
 
-  queue ifield;                /* input field mapping */
-  queue* ofield;               /* output field mapping */
-  QList<field_map> ifields;
-  QList<field_map> ofields;
-
-  int ifield_ct;               /* actual # of ifields */
-  int ofield_ct;               /* actual # of ofields */
+  QList<field_map> ifields;    /* input field mapping */
+  QList<field_map> ofields;    /* output field mapping */
 
   gpsbabel::File* file;
   QTextStream* stream;
diff --git a/xcsv.cc b/xcsv.cc
index d93aec2067b2157127f5f301f1195d5013007e59..55e91b22d5aa467276d36ad90f4a7391dbeb05bd 100644 (file)
--- a/xcsv.cc
+++ b/xcsv.cc
 
  */
 
-#include <QtCore/QTextCodec>
-#include <QtCore/QTextStream>
-#include <QtCore/QDebug>
+#include <QtCore/QByteArray>   // for QByteArray
+#include <QtCore/QHash>        // for QHash
+#include <QtCore/QString>      // for QString
+#include <QtCore/QStringList>  // for QStringList
+#include <QtCore/QTextCodec>   // for QTextCodec
+#include <QtCore/QTextStream>  // for QTextStream
+#include <QtCore/QtGlobal>     // for qPrintable
 
 #include <cctype>
 #include <cstdlib>
@@ -110,8 +114,6 @@ char_map_t xcsv_char_table[] = {
 void
 xcsv_destroy_style(void)
 {
-  queue* elem, *tmp;
-  field_map_t* fmp;
 
   /*
    * If this xcsv_file struct came from a file we can free it all.
@@ -125,45 +127,8 @@ xcsv_destroy_style(void)
   xcsv_file.epilogue.clear();
 
   /* destroy the ifields */
-  QUEUE_FOR_EACH(&xcsv_file.ifield, elem, tmp) {
-    fmp = reinterpret_cast<field_map_t *>(elem);
-    if (fmp->key) {
-      xfree(fmp->key);
-    }
-    if (fmp->val) {
-      xfree(fmp->val);
-    }
-    if (fmp->printfc) {
-      xfree(fmp->printfc);
-    }
-    if (elem) {
-      xfree(elem);
-    }
-  }
-
-  /* destroy the ofields, if they are not re-mapped to ifields. */
-  if (xcsv_file.ofield != &xcsv_file.ifield) {
-    QUEUE_FOR_EACH(xcsv_file.ofield, elem, tmp) {
-      fmp = reinterpret_cast<field_map_t *>(elem);
-      if (fmp->key) {
-        xfree(fmp->key);
-      }
-      if (fmp->val) {
-        xfree(fmp->val);
-      }
-      if (fmp->printfc) {
-        xfree(fmp->printfc);
-      }
-      if (elem) {
-        xfree(elem);
-      }
-    }
-
-    if (xcsv_file.ofield) {
-      xfree(xcsv_file.ofield);
-    }
-  }
   xcsv_file.ifields.clear();
+  /* destroy the ofields */
   xcsv_file.ofields.clear();
 
   /* other alloc'd glory */
@@ -185,7 +150,7 @@ xcsv_destroy_style(void)
 
 // Given a keyword of "COMMASPACE", return ", ".
 QString
-xcsv_get_char_from_constant_table(QString key)
+xcsv_get_char_from_constant_table(const QString& key)
 {
   static QHash<QString, QString> substitutions;
   if (substitutions.empty()) {
@@ -202,7 +167,7 @@ xcsv_get_char_from_constant_table(QString key)
 
 // Remove outer quotes.
 // Should probably be in csv_util.
-static QString dequote(QString in) {
+static QString dequote(const QString& in) {
   QString r = in.simplified();
   if (r.startsWith("\"")) r = r.mid(1);
   if (r.endsWith("\"")) r.chop(1);
@@ -347,12 +312,9 @@ xcsv_parse_style_line(QString line)
 
     // The key ("LAT_DIR") should never contain quotes.
 
-    const char* key = xstrdup(tokens[0].simplified());
-    QString s1 = dequote(tokens[1]);
-    char* val = xstrdup(s1);
-
-    QString s2 = dequote(tokens[2]);
-    char* pfc = xstrdup(s2);
+    const QString key = tokens[0].simplified();
+    const QString val = dequote(tokens[1]);
+    const QString pfc = dequote(tokens[2]);
     xcsv_ifield_add(key, val, pfc);
   } else
 
@@ -362,20 +324,16 @@ xcsv_parse_style_line(QString line)
       //  change the world on ifield vs ofield format later..
       //
   if (op == "OFIELD") {
-    int options = 0;
+    unsigned options = 0;
       // Note: simplifieid() has to run after split().
     if (tokens.size() < 3) {
       Fatal() << "Invalid OFIELD line: " << tokenstr;
     }
 
     // The key ("LAT_DIR") should never contain quotes.
-    const char *key = xstrdup(tokens[0].simplified());
-
-    QString s1 = dequote(tokens[1]);
-    char *val = xstrdup(s1);
-
-    QString s2 = dequote(tokens[2]);
-    const char* pfc = xstrdup(s2);
+    const QString key = tokens[0].simplified();
+    const QString val = dequote(tokens[1]);
+    const QString pfc = dequote(tokens[2]);
 
     // This is pretty lazy way to parse write options.
     // They've very rarely used, so we'll go for simple.
@@ -422,12 +380,8 @@ xcsv_read_style(const char* fname)
   }
 
   /* if we have no output fields, use input fields as output fields */
-  if (xcsv_file.ofield_ct == 0) {
-    if (xcsv_file.ofield) {
-      xfree(xcsv_file.ofield);
-    }
-    xcsv_file.ofield = &xcsv_file.ifield;
-    xcsv_file.ofield_ct = xcsv_file.ifield_ct;
+  if (xcsv_file.ofields.isEmpty()) {
+    xcsv_file.ofields = xcsv_file.ifields;
   }
   gbfclose(fp);
 }
@@ -446,12 +400,8 @@ xcsv_read_internal_style(const char* style_buf)
   xcsv_parse_style_buff(style_buf);
 
   /* if we have no output fields, use input fields as output fields */
-  if (xcsv_file.ofield_ct == 0) {
-    if (xcsv_file.ofield) {
-      xfree(xcsv_file.ofield);
-    }
-    xcsv_file.ofield = &xcsv_file.ifield;
-    xcsv_file.ofield_ct = xcsv_file.ifield_ct;
+  if (xcsv_file.ofields.isEmpty()) {
+    xcsv_file.ofields = xcsv_file.ifields;
   }
 }